{"componentChunkName":"component---node-modules-gatsby-theme-chronoblog-src-templates-post-js","path":"/api-testing-with-nightwatch-supertest/","result":{"data":{"mdx":{"id":"cafa8e5b-f819-5488-be2e-18563d87bebe","excerpt":"When the software being tested exposes REST API endpoints it can be more efficient to test the APIs directly instead of going through the UI…","frontmatter":{"title":"Add API Testing to your Nightwatch Test Automation","date":"2023-01-13T00:00:00.000Z","description":"Learn how to add API testing to your existing selenium automated tests using the API testing plugin for Nightwatch.js","tags":["quality assurance","software testing","nightwatchjs","selenium","post'"],"cover":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wgARCAAMABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAYHAgX/xAAVAQEBAAAAAAAAAAAAAAAAAAACA//aAAwDAQACEAMQAAABldIQcxXWFkof/8QAGxAAAgMAAwAAAAAAAAAAAAAAAwQBAgUGExX/2gAIAQEAAQUCwePtki+Z1w+lWh19xjxAaRxQZ0xr/wD/xAAXEQADAQAAAAAAAAAAAAAAAAABAhEQ/9oACAEDAQE/AWEmf//EABcRAAMBAAAAAAAAAAAAAAAAAAACIQH/2gAIAQIBAT8BrCzKf//EACMQAAEDAgUFAAAAAAAAAAAAAAEAAhEDEgQUISIxBRNCgqH/2gAIAQEABj8CGKqMGSc4tkkTzCAFKmfQKNo08BCHToZl7u9xrdC2u+K5ztV//8QAGxAAAgMAAwAAAAAAAAAAAAAAAREAITFhkbH/2gAIAQEAAT8hR9YslFbss6gtjGlipPqChBAAVfI8haQh6wPsvbAKgp//2gAMAwEAAgADAAAAEFzv/8QAGBEAAgMAAAAAAAAAAAAAAAAAARARMUH/2gAIAQMBAT8QrtEr/8QAGhEBAAMAAwAAAAAAAAAAAAAAAQARITHB8P/aAAgBAgEBPxBBarGt91Aicp//xAAbEAEAAgMBAQAAAAAAAAAAAAABESEAMWGBUf/aAAgBAQABPxB5rfOKBsJqRsZ1eGikJFYItS2Ln3L943V7gX3FNNyTAV7IjmqxGXSyxwOMoUFEwaoD7n//2Q==","aspectRatio":1.6842105263157894,"src":"/static/c1591e1a57d42702a2a7d9e25086290c/3e61c/nightwatch-api-testing.jpg","srcSet":"/static/c1591e1a57d42702a2a7d9e25086290c/7fcb3/nightwatch-api-testing.jpg 192w,\n/static/c1591e1a57d42702a2a7d9e25086290c/42594/nightwatch-api-testing.jpg 384w,\n/static/c1591e1a57d42702a2a7d9e25086290c/3e61c/nightwatch-api-testing.jpg 768w","srcWebp":"/static/c1591e1a57d42702a2a7d9e25086290c/dd090/nightwatch-api-testing.webp","srcSetWebp":"/static/c1591e1a57d42702a2a7d9e25086290c/ae504/nightwatch-api-testing.webp 192w,\n/static/c1591e1a57d42702a2a7d9e25086290c/fef30/nightwatch-api-testing.webp 384w,\n/static/c1591e1a57d42702a2a7d9e25086290c/dd090/nightwatch-api-testing.webp 768w","sizes":"(max-width: 768px) 100vw, 768px","presentationWidth":768,"presentationHeight":455},"resize":{"src":"/static/c1591e1a57d42702a2a7d9e25086290c/3e61c/nightwatch-api-testing.jpg"}}}},"fields":{"slug":"/api-testing-with-nightwatch-supertest/"},"body":"var _excluded = [\"components\"];\nfunction _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n/* @jsxRuntime classic */\n/* @jsx mdx */\n\nvar _frontmatter = {\n  \"title\": \"Add API Testing to your Nightwatch Test Automation\",\n  \"cover\": \"./nightwatch-api-testing.jpg\",\n  \"date\": \"2023-01-13T00:00:00.000Z\",\n  \"description\": \"Learn how to add API testing to your existing selenium automated tests using the API testing plugin for Nightwatch.js\",\n  \"tags\": [\"quality assurance\", \"software testing\", \"nightwatchjs\", \"selenium\", \"post'\"]\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n    props = _objectWithoutProperties(_ref, _excluded);\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"When the software being tested exposes REST API endpoints it can be more efficient to test the APIs directly instead of going through the UI. If the business logic is in the API you can cut out the middle man, the browser, and make the calls directly--eliminating flakiness due to page load times for example. There are many solutions for testing REST APIs including.\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Postman\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"SuperTest\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"RestAssured\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"SoapUI\")), mdx(\"h2\", {\n    \"id\": \"testing-rest-apis-from-your-selenium-test-projects\"\n  }, \"Testing REST APIs from your Selenium Test Projects\"), mdx(\"p\", null, \"The downside of these tools is they didn't, until recently, integrate with one's existing selenium UI automated test suite. The API tests would live in a separate framework or solution. Being able to test and interact with one's APIs from one's UI tests offers several advantages including\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Better organization of one's tests, everything in one place\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Setup of pre/post conditions (state) for the UI tests through the API\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Assert results of UI interaction more efficiently at the API layer\")), mdx(\"p\", null, \"So, one can write test cases where it makes sense to, as pure API tests, or mix in API checks and calls within one's selenium tests.\"), mdx(\"p\", null, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/nightwatchjs/nightwatch/releases/tag/v2.5.2\"\n  }, \"Nightwatch 2.5.2\"), \" integrated SuperTest into its selenium test framework allowing one to use SuperTest in their existing test suites. This tutorial will explore how Nightwatch and SuperTest work in practice when compared to other frameworks that offer similar capabilities, like Playwright.\"), mdx(\"h2\", {\n    \"id\": \"initial-thoughts\"\n  }, \"Initial Thoughts\"), mdx(\"p\", null, \"I've used \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.npmjs.com/package/supertest\"\n  }, \"SuperTest\"), \" off and on for years so I was happy to learn Nightwatch integrated it into its framework to add API testing. It's easy to use and has a nice fluent assertion style.\"), mdx(\"p\", null, \"I don't like the fact it needs to be imported as a plugin (\", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/nightwatchjs/nightwatch-plugin-apitesting\"\n  }, \"@nightwatch/apitesting\"), \"). I feel this should be a more core feature and included as default. In addition, when working with TypeScript, the Nightwatch plugin system and TypeScript types are still having growing pains.\"), mdx(\"p\", null, \"Importing the plugin and adding custom types is not difficult. This article will go over both, but it's something that just works out of the box with competing frameworks like Playwright. Still, this is a nice addition of functionality for quality engineers with an existing Nightwatch test suite and I'm happy to see continuous innovation being made.\"), mdx(\"p\", null, \"So, let's get started API testing.\"), mdx(\"h2\", {\n    \"id\": \"api-testing-in-nightwatch-selenium-projects\"\n  }, \"API Testing in Nightwatch Selenium Projects\"), mdx(\"p\", null, \"This tutorial will go through creating a Nightwatch TypeScript selenium test project, import the API Testing plugin, add type definitions for TypeScript support, and write example tests against some \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"../best-websites-for-practicing-test-automation/\"\n  }, \"practice REST APIs\"), \".\"), mdx(\"h3\", {\n    \"id\": \"initial-installation\"\n  }, \"Initial Installation\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"From a command line run \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"npm init nightwatch@latest\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"During the guided setup select end-to-end testing and TypeScript\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Continue through accepting defaults for the remaining prompts.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Add the API testing plugin by running \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"npm install @nightwatch/apitesting @types/supertest --save-dev\"))), mdx(\"p\", null, \"This will create a default working Nightwatch TypeScript test project with sample tests under \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"/nightwatch/\")), mdx(\"p\", null, \"They can be executed using \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"npx nightwatch\")), mdx(\"h3\", {\n    \"id\": \"configuring-the-test-project\"\n  }, \"Configuring the Test Project\"), mdx(\"p\", null, \"Now that there is a working test project we can \", mdx(\"del\", {\n    parentName: \"p\"\n  }, \"add custom TypeScript types for API testing\"), \"(edit 1/24/22 now included in \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/nightwatchjs/nightwatch-plugin-apitesting/blob/main/nightwatch/types/index.d.ts\"\n  }, \"v0.2.2\"), \"), remove the sample tests, and create our own API tests.\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Remove the sample tests out of \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"./nightwatch/\"), \", but leave \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"tsconfig.json\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Create a folder \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"./nightwatch/tests\"), \" \"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Edit \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"./nightwatch.conf.js\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Change \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"src_folders\"), \" to \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"src_folders: ['nightwatch/tests'],\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Change \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"plugins\"), \" to \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"plugins: ['@nightwatch/apitest'],\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Optionally, to prevent a browser from launching, useful in a pure API test suite, one can modify the start_session and start_process values to false.\")), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"// nightwatch.conf.js\\n// ...\\n  test_settings: {\\n    default: {\\n      // ...\\n      start_session: false,\\n      webdriver: {\\n        start_process: false,\\n        server_path: ''\\n      },\\n      \\n    },\\n  }\\n\")), mdx(\"p\", null, \"You can checkout the example solution with this preconfigured from my GitHub under \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/reallymello/nightwatchTutorials/tree/master/apiTesting\"\n  }, \"nightwatchTutorials/apiTesting\"), \" to follow along. \", mdx(\"em\", {\n    parentName: \"p\"\n  }, \"I'll try to keep this repository updated as updates occur to the API testing plugin over time.\")), mdx(\"h3\", {\n    \"id\": \"writing-your-first-api-test\"\n  }, \"Writing your first API Test\"), mdx(\"p\", null, \"The example test solution has example tests written against the Swagger PetStore and Restful Booker test playground APIs (see more on \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"../best-websites-for-practicing-test-automation/\"\n  }, \"Best Websites to Practice Test Automation\"), \").\"), mdx(\"p\", null, \"First, let's create a test against \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://petstore.swagger.io/#/store/getInventory\"\n  }, \"/store/inventory\"), \".\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Create a file called petStore.ts under \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"./nightwatch/tests/\"))), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"// petStore.ts\\nimport { NightwatchBrowser, NightwatchTests } from \\\"nightwatch\\\";\\n// This line will add the api testing command types to the Nightwatch API\\nimport '@nightwatch/apitesting';\\n\\nconst petStoreTests: NightwatchTests = {\\n};\\n\\nexport default petStoreTests;\\n\")), mdx(\"p\", null, \"This will be the shell of your tests against the pet store API. It brings in the TypeScript types applicable for Nightwatch API tests. Now, let's create the test.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"import { NightwatchBrowser, NightwatchTests } from \\\"nightwatch\\\";\\nimport '@nightwatch/apitesting';\\n\\nconst petStoreTests: NightwatchTests = {\\n    // You pass supertest into the test through the object. The test must be async/awaited\\n    'can GET count of sold inventory': async ({ supertest }: NightwatchBrowser) => {\\n      await supertest\\n        // Request can take a a baseUrl for a remote API or the entry point of a REST API, like Express()\\n        .request('https://petstore.swagger.io/v2')\\n        // After request, the syntax exactly matches supertest and chai\\n        .get('/store/inventory/')\\n        .expect(200)\\n        .expect('Content-Type', /json/)\\n        .then((response) => {\\n          expect(response.body.sold).to.be.greaterThan(0);\\n        });\\n    },\\n  };\\n  \\nexport default petStoreTests;\\n\")), mdx(\"p\", null, \"For those used to supertest this is very familiar. The one oddity I found was the await returns an \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/nightwatchjs/nightwatch-plugin-apitesting/issues/2\"\n  }, \"@nightwatch_element response\"), \" instead of the supertest response which requires one to do assertions against the response in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"then\"), \" block.\"), mdx(\"p\", null, \"POST requests are very similar and one can easily put a JSON object inside the .send method as shown.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"    'can POST a pet to the store': async ({ supertest }: NightwatchBrowser) => {\\n      await supertest\\n        .request('https://petstore.swagger.io/v2')\\n        .post('/store/order')\\n        .send({\\n          id: 0,\\n          petId: 31337,\\n          quantity: 1,\\n          shipDate: '2022-12-30T14:55:04.147Z',\\n          status: 'placed',\\n          complete: true,\\n        })\\n        .expect(200)\\n        .expect('Content-Type', /json/)\\n        .then((response) => {\\n          expect(response.body.id).to.be.greaterThan(0);\\n          expect(response.body.quantity).to.equal(1);\\n          expect(response.body.status).to.equal('placed');\\n        });\\n    },\\n\")), mdx(\"h3\", {\n    \"id\": \"more-advanced-api-testing\"\n  }, \"More Advanced API Testing\"), mdx(\"p\", null, \"The Restful Booker has a more realistic stateful database (that gets wiped every 10 minutes) so it is better to construct scenario-based API tests against. I have examples under \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/reallymello/nightwatchTutorials/blob/master/apiTesting/nightwatch/tests/restfulBooker.ts\"\n  }, \"/apiTesting/nightwatch/tests/restfulBooker.ts\"), \" that illustrate that including partial updates using the PATCH verb.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"  'Can partially update booking': async ({ supertest }: NightwatchBrowser) => {\\n    await supertest\\n      .request(baseUrl)\\n      .patch(`/booking/${bookingId}`)\\n      .set('Content-type', 'application/json')\\n      .set('Cookie', `token=${authToken.token}`)\\n      .accept('application/json')\\n      .send({\\n        totalprice: 200,\\n        depositpaid: false,\\n        bookingdates: {\\n          checkin: '2023-03-31',\\n          checkout: '2023-04-15',\\n        },\\n        additionalneeds: 'an even-numbered floor',\\n      })\\n      .then((response: any) => {\\n        expect(response.body).to.have.property('depositpaid', false);\\n        expect(response.body).to.have.property(\\n          'additionalneeds',\\n          'an even-numbered floor'\\n        );\\n        expect(response.body).to.have.property('totalprice', 200);\\n        expect(response.body.bookingdates).to.have.property(\\n          'checkin',\\n          '2023-03-31'\\n        );\\n        expect(response.body.bookingdates).to.have.property(\\n          'checkout',\\n          '2023-04-15'\\n        );\\n      });\\n  },\\n\")), mdx(\"p\", null, \"Another oddity, I found (as of writing) \", mdx(\"del\", {\n    parentName: \"p\"\n  }, \"was no documented way of using supertest in the before pretest hook to do something like grab and store an authentication token to use in the tests later. I ended up importing superagent to do that in this test suite which worked out, but didn't seem polished.\")), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"import { NightwatchBrowser, NightwatchTests } from 'nightwatch';\\nimport superagent from 'superagent';\\n//...\\nlet authToken: token;\\n\\nconst bookerTests: NightwatchTests = {\\n  before: async () => {\\n    authToken = (\\n      await superagent.post(`${baseUrl}/auth`).send({\\n        username: 'admin',\\n        password: 'password123',\\n      })\\n    ).body;\\n  },\\n//...\\n\")), mdx(\"p\", null, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"1/13/23 Update\"), \" - I learned you can use it in the before test hook off of the Nightwatch API object (aka browser or client). So one could rewrite the above example removing the need to import superagent using the style below.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"const bookerTests: NightwatchTests = {\\n  before: async (client: NightwatchBrowser) => {\\n    await client.supertest\\n      .request(baseUrl)\\n      .post('/auth')\\n      .send({\\n        username: 'admin',\\n        password: 'password123',\\n      })\\n      .expect(200)\\n      .expect('Content-type', 'application/json; charset=utf-8')\\n      .then((response: any) => {\\n        authToken = response.body;\\n      });\\n  },\\n\")), mdx(\"p\", null, \"Last, you can load up your API locally into supertest by passing it the entry point of your Express() application (or NestJS) which is useful for local testing. An example of that can be found under, \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/reallymello/nightwatchTutorials/blob/master/apiTesting/nightwatch/tests/restfulBookerLocal.ts\"\n  }, \"apiTesting/nightwatch/tests/restfulBookerLocal.ts\"), \".\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"const server = require('../../restfulBooker/restful-booker/app');\\n// ...\\n'Can GET ping': async ({ supertest }: NightwatchBrowser) => {\\n    await supertest.request(server).get('/ping').expect(201);\\n},\\n\")), mdx(\"h3\", {\n    \"id\": \"executing-the-tests\"\n  }, \"Executing the tests\"), mdx(\"p\", null, \"To run the tests, you can run all or specific tests using the standard Nightwatch command line syntax.\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"npx nightwatch\"), \" \")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"npx nightwatch --test testPathHere\"), \" \"))), mdx(\"p\", null, \"You get the same nice test reporting that was added in Nightwatch 2.0.\"), mdx(\"span\", {\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"820px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"143.41463414634146%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAdCAYAAACqhkzFAAAACXBIWXMAABJ0AAASdAHeZh94AAAEV0lEQVRIx41V13bbWBDTa5J1EUVSJMXeRRWrV9uyvdlNTv7/f7CYkSXXnM0DDovEuXMBDG7L8hO4YQo3yuCnJXpJofdyFXTDCG6cIshqGE6AthPCCPMjghSGn+p9m9dLy0NLXwQZOvKHXoqOn+HK9HDZcQgXV4Rc/zK6uOA7hdx/Bv7W8sICcdGgHQUwohDtmF1EPq47nhaT6zUXuNCijuJcWMEFpQHTxQXR6vgh6psZsv4ISdWgGk/1OalH6I9nSOshLD+G1YtJRa5wuFWbVAnk/bXd0+JStNVNUzz9/IXl9hbr/QF3T9+xPzxhxfvV/h41F5gsNxjPVxhMFyiaMdJqAIe8C+xehCvLeylosMMh/1wNb5Czq2o4OWIwQZT3tYsuO/LYmeH4+Na2lc9v7SNO3OqWhUOrF8AsuErcQ68sIR37VYUO+fxq2vh6/Vzg+UPpRj7+HVrdICFfQ9gJ+cgSOHkGJ8tg59xSnsPyThwdO3gR5SSGd+5OOzTjCNvDI2bLLdbbO6x2B6x398SBvN4pfzkFq0dT3CzWGJGeyWLD5wlMN1R0CPGodN+Szm4fv+uH8+0Oi90ttvePWFAkxe4Ow8lCXSCqN5M5+nRBORjrIMgORZwuub62PbFNgGo2VeVEiGY8x2i61Oeo6NNKA1U2J+ReCkd5rb+1uz3l94QXUfIYF6EHt8hhpjHsMOG0uPhyZRIWhbHOHL0uIPggis12i+aGCnNuC85zv0JY1PDiQhGklRr5yuqpOO2urxDOjG6g7wVn2wiHD//+xHy1oyB3uH34Gw///MBss8NsvVdzyzvleLPH+vag9zG3LGKcPHguaHDL/elcecn7Y+WrIE8hO5O0CbKK0zJTlWVqRBThV7p8bejzpNicFLOMj8auuO2MU8FrJ6axDVsn4ws5VCinpt6LH0/F3nRoU3ZRzk5oZIqioLm7hPwmw+8w3rr+MTMlHI4W8c+8vuHQimPcf/+hVpFwEB5XNHQ9nOr2m5s59uRwx8DYPzzhQH6n5ND0ws+3bMUJJ+UJQybJZLXBaLbChsSLefvPnIkI9YhmZoBI4rhhdrbMhy2bjPjpZstOZgr5WEZuwEIDTshwtuRiS83FvDmmkYiTSU56n6jc8TzYNaM/ifQj8WBcNuQu0i5kPmVe5fkIGt9/CdXX0C07bD+rRlqwndKsjDKD49hxjkOvoImPHbjn1JGUkcVOePGhR7v0S/h5iYIBm7N4Q74SnjPClZx2Pv1oPBd9W8T7EGH0IY/JMsdl1NM8lE6tnLbgQXVhcXZfpfL/4XmWE1ScgqCsNKmjpkEyGCAeDhBweuREPI2ZdCXcvccbH7YdbiPh0AcBQo6ZnB0hC1keRem8TZM/6tCNc/ptDqfMYGacippHZb+AM2Da1KUuIAfVexHe40UUt6fF3CRHVg6Q5A3KPuOMhfQspjAmuz126f0Gr9OGW77MPBXFpCAGQ0GEkSKy8unY/FNR/gNWbg4iyjIsVwAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"img\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"Nightwatch API Test Output\",\n    \"title\": \"Nightwatch API Test Output\",\n    \"src\": \"/static/5d3542ddd14b06f843cf84dd6f9f5265/083f8/apiTestOutput.png\",\n    \"srcSet\": [\"/static/5d3542ddd14b06f843cf84dd6f9f5265/ad4a5/apiTestOutput.png 205w\", \"/static/5d3542ddd14b06f843cf84dd6f9f5265/74ab4/apiTestOutput.png 410w\", \"/static/5d3542ddd14b06f843cf84dd6f9f5265/083f8/apiTestOutput.png 820w\", \"/static/5d3542ddd14b06f843cf84dd6f9f5265/42ccd/apiTestOutput.png 897w\"],\n    \"sizes\": \"(max-width: 820px) 100vw, 820px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\"\n  }), \"\\n    \"), mdx(\"p\", null, \"The results also present nicely in the improved Nightwatch HTML test report.\"), mdx(\"span\", {\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"820px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"73.65853658536585%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAABJ0AAASdAHeZh94AAACM0lEQVQ4y4WTW2/aQBCF/WO4CKRGPPDAQxGR+tCX/naktAEacWlF1FDsZX1b27tem5OZBVMSNcLSJ9uz3tmZc8bet69fMBwOMRgM0O120el00G633b3VauHu0x0m9/eYTCbo9Xoudr3e7/cxHo+JzxiNRvCm0ym+PzxgsVhgNpthPp9jtV5hvV5f2Gw2/7iKO1YrLJdLPM6e8OPxJzxbVcgLDWMMPrp4rSxLx63L20uF5VYiCEPsZQARS4gkxN+DjyiNofMMYrcjXhAGPrIoQpmpC5owKnXPJs/hxcrQ5gyFNiiKAjkFmSzLoLmyIof48wzx8oxECOR0sIljmOREkSbQcQRNhxva49V1hbquUVHrTF3V7v1NrHknrIudnnnNlhbGWpS6IEkMvGbD8Xh0WNIppxYYQ9VZ/vAKe3Xn9Tg8IIkksjhETlV6ObdGrRqjXUKlEmx/rfB7+YTteolECtIocS29pyBUdKBkEnkSObxA+BAiQHl2UucKcbBziaJDQEJnsHQYV2TNezSqM/aMxwaoswE1VVhqMoXKt6RHdZaiufiR397gpDqtubHJ0hTC9yHJQZUkrlJDlbLL7HrjvCXhcUnwf9gPLyPrD/s9zVhAmqSobImYYkqpk4uUiLk27iO0ppYLciqkYY2pOt5YVZb+nNMs8gfNXPLfcish7/cymnBJwyqlJEI3SwklFyRBSPGAKvdJEo7dSsiH0tgocJVOO6qIW+ZW2XE+sfmHbyVjWJZX7vlb0NWS/5MAAAAASUVORK5CYII=')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"img\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"Nightwatch HTML Test Report\",\n    \"title\": \"Nightwatch HTML Test Report\",\n    \"src\": \"/static/cfe787d438b85b4510b2e5360760499f/083f8/htmlTestReport.png\",\n    \"srcSet\": [\"/static/cfe787d438b85b4510b2e5360760499f/ad4a5/htmlTestReport.png 205w\", \"/static/cfe787d438b85b4510b2e5360760499f/74ab4/htmlTestReport.png 410w\", \"/static/cfe787d438b85b4510b2e5360760499f/083f8/htmlTestReport.png 820w\", \"/static/cfe787d438b85b4510b2e5360760499f/8ffbc/htmlTestReport.png 1128w\"],\n    \"sizes\": \"(max-width: 820px) 100vw, 820px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\"\n  }), \"\\n    \"), mdx(\"h2\", {\n    \"id\": \"final-thoughts\"\n  }, \"Final Thoughts\"), mdx(\"p\", null, \"Nightwatch has been rapidly releasing interesting new features throughout 2022 and now into 2023 such as visual regression testing, component testing, enhancements to reporting and debugging, and improved mobile testing. Their implementation of API Testing is one of the newer additions and I think it shows promise, but it feels like it needs more polish compared to other popular frameworks like Playwright.\"), mdx(\"p\", null, \"Playwright's API testing\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Is included by default (not a plugin)\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"del\", {\n    parentName: \"li\"\n  }, \"Has included TypeScript types\"), \" \", mdx(\"em\", {\n    parentName: \"li\"\n  }, \"now included in the Nightwatch plugin as well\")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Has better documentation\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Has a handy \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"test.use\"), \" that let's you default tedious settings like baseUrl, headers, and authorization\")), mdx(\"p\", null, \"What Nightwatch does better\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Better assertion style\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Nicer test output/HTML report\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Perhaps better support for local testing/mocking API requests\")), mdx(\"p\", null, \"Overall, the API testing capability added to Nightwatch is a useful addition and will hopefully improve in coming iterations.\"), mdx(\"p\", null, \"For further learning consider checking out some API testing books\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://amzn.to/3VX5xar\"\n  }, \"Testing Web APIs\")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://amzn.to/3ipaxXJ\"\n  }, \"Learn API Testing\"))), mdx(\"p\", null, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"As an Amazon Associate I earn from qualifying purchases made through links on this site (which helps support it, thank you!)\")));\n}\n;\nMDXContent.isMDXComponent = true;"}},"pageContext":{"id":"cafa8e5b-f819-5488-be2e-18563d87bebe"}},"staticQueryHashes":["1961101537","2542493696"]}